feat: update Releases API#61
Conversation
|
Warning Review limit reached
Next review available in: 37 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughRelease APIs now support paginated responses, expanded release and tag schemas, CRUD operations, label detachment, and new work-item, comment, and link sub-resources. Tests cover lifecycle behavior, pagination envelopes, compatibility fields, and deletion failures. ChangesRelease API expansion
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant Releases
participant ReleaseComments
participant ReleaseLinks
participant API
Client->>Releases: list/retrieve/update/delete release
Releases->>API: GET/PATCH/DELETE release endpoint
Client->>ReleaseComments: create/update/delete comment
ReleaseComments->>API: POST/PATCH/DELETE comment endpoint
Client->>ReleaseLinks: create/update/delete link
ReleaseLinks->>API: POST/PATCH/DELETE link endpoint
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plane/api/releases/base.py`:
- Around line 35-48: Update each list method—Release.list in
plane/api/releases/base.py (35-48), Tag.list in plane/api/releases/tags.py
(21-34), Label.list in plane/api/releases/labels.py (21-34), ItemLabel.list in
plane/api/releases/item_labels.py (20-34), WorkItem.list in
plane/api/releases/work_items.py (19-33), Comment.list in
plane/api/releases/comments.py (21-35), and Link.list in
plane/api/releases/links.py (21-35)—to accept its corresponding typed Pydantic
query DTO instead of Mapping[str, Any], and pass params serialized with
model_dump(exclude_none=True) to _get.
In `@plane/api/releases/item_labels.py`:
- Around line 52-63: Update the delete method to accept the appropriate Pydantic
label-removal DTO, replacing the inline {"label_ids": [label_id]} dictionary
with that DTO’s model_dump(exclude_none=True) result when calling _delete.
Preserve the existing workspace, release, and label endpoint behavior.
In `@plane/api/releases/work_items.py`:
- Around line 35-59: Rename the release work-item methods `add` and `remove` to
the CRUD names `create` and `delete`. Update `delete` to accept the Pydantic
removal DTO instead of `list[str]`, and serialize that DTO with
`model_dump(exclude_none=True)` when passing its payload to `_delete`; preserve
the existing endpoint and create behavior.
In `@plane/models/releases.py`:
- Around line 116-129: Update the CreateReleaseTag model so version is a
required string rather than an optional field with a None default. Preserve the
existing optionality of description, commit_hash, and git_tag.
In `@tests/unit/test_releases.py`:
- Around line 35-38: Update each cleanup block around client.releases.delete to
catch only the expected HttpError for an already-deleted release, while
re-raising HttpError instances with other status codes and all non-HTTP
exceptions. Apply the same behavior to every listed cleanup occurrence,
preserving successful deletion handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2a30ce34-2179-4eba-9dd1-86e89287e053
📒 Files selected for processing (10)
plane/api/releases/base.pyplane/api/releases/comments.pyplane/api/releases/item_labels.pyplane/api/releases/labels.pyplane/api/releases/links.pyplane/api/releases/tags.pyplane/api/releases/work_items.pyplane/models/releases.pypyproject.tomltests/unit/test_releases.py
| def list( | ||
| self, workspace_slug: str, params: Mapping[str, Any] | None = None | ||
| ) -> PaginatedReleaseResponse: | ||
| """List releases in the workspace (paginated). | ||
|
|
||
| def list(self, workspace_slug: str) -> list[Release]: | ||
| """List all releases in the workspace. | ||
| Returns one page (20 by default). Pass `per_page`/`cursor` in params and | ||
| follow `next_cursor` to page through the rest. | ||
|
|
||
| Args: | ||
| workspace_slug: The workspace slug identifier | ||
| params: Optional query parameters, e.g. `per_page`, `cursor` | ||
| """ | ||
| response = self._get(f"{workspace_slug}/releases/") | ||
| return [Release.model_validate(item) for item in response] | ||
| response = self._get(f"{workspace_slug}/releases/", params=params) | ||
| return PaginatedReleaseResponse.model_validate(response) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Use typed Pydantic models for pagination parameters.
The new list methods expose raw Mapping[str, Any] inputs, bypassing validation and the repository’s DTO contract.
plane/api/releases/base.py#L35-L48: accept and serialize a release-list query model.plane/api/releases/tags.py#L21-L34: accept and serialize a tag-list query model.plane/api/releases/labels.py#L21-L34: accept and serialize a label-list query model.plane/api/releases/item_labels.py#L20-L34: accept and serialize an item-label query model.plane/api/releases/work_items.py#L19-L33: accept and serialize a work-item query model.plane/api/releases/comments.py#L21-L35: accept and serialize a comment query model.plane/api/releases/links.py#L21-L35: accept and serialize a link query model.
As per coding guidelines, resource methods must accept Pydantic DTOs and serialize them with model_dump(exclude_none=True).
📍 Affects 7 files
plane/api/releases/base.py#L35-L48(this comment)plane/api/releases/tags.py#L21-L34plane/api/releases/labels.py#L21-L34plane/api/releases/item_labels.py#L20-L34plane/api/releases/work_items.py#L19-L33plane/api/releases/comments.py#L21-L35plane/api/releases/links.py#L21-L35
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@plane/api/releases/base.py` around lines 35 - 48, Update each list
method—Release.list in plane/api/releases/base.py (35-48), Tag.list in
plane/api/releases/tags.py (21-34), Label.list in plane/api/releases/labels.py
(21-34), ItemLabel.list in plane/api/releases/item_labels.py (20-34),
WorkItem.list in plane/api/releases/work_items.py (19-33), Comment.list in
plane/api/releases/comments.py (21-35), and Link.list in
plane/api/releases/links.py (21-35)—to accept its corresponding typed Pydantic
query DTO instead of Mapping[str, Any], and pass params serialized with
model_dump(exclude_none=True) to _get.
Source: Coding guidelines
…quest models for deletion
Description
Brings the SDK's releases surface in line with the API.
Added
releases—retrieve,deletereleases.tags/releases.labels—retrieve,update,deletereleases.work_items—list,add,removereleases.comments— full CRUDreleases.links— full CRUDFixed
list()raisedValidationError: the endpoints return a paginated envelope, but the SDK iterated it as a list. They now parse the envelope (Paginated*Response) and acceptper_page/cursor.ReleaseTagwas modeled as a label (name/color). A tag is a version marker — it now carriesversion,commit_hash,git_tag,description.CreateReleaseTagsends the requiredversion.item_labels.deletecalled a route that does not exist; it now detaches viaDELETE /releases/{id}/labels/with alabel_idsbody.Releasedropped fields the API never returns and gained the real ones (target_date,lead,tag,is_latest,is_prerelease,external_source,external_id). The body is written withdescription_html/description_json;descriptionreads back as a nested object.Type of Change
Test Scenarios
tests/unit/test_releases.pyrewritten: 8 → 25 tests covering releases, tags, labels, item labels, work items, comments, links, and the backward-compatibility guarantees.References
Version bumped to 0.2.20.
Summary by CodeRabbit